home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / progtool / modula2 / pl0 / pl0scann.mod < prev    next >
Encoding:
Modula Implementation  |  1994-09-22  |  5.3 KB  |  292 lines

  1.  
  2.  
  3. IMPLEMENTATION MODULE PL0Scanner;
  4.  
  5. FROM Terminal IMPORT Read, BusyRead;
  6.  
  7. FROM FileSystem IMPORT ReadChar;
  8.  
  9. FROM TextWindows IMPORT Window, OpenTextWindow, Write, WriteCard,
  10.                  Invert, CloseTextWindow;
  11.                  
  12. FROM Windows IMPORT Title, WindowElements;
  13.  
  14.  
  15. CONST
  16.   maxCard = 177777B;
  17.   bufLen = 1000;
  18.   
  19. VAR
  20.   ch : CHAR;
  21.   id0, id1 : CARDINAL;
  22.   win : Window;
  23.   keyTab : ARRAY [1..20] OF RECORD
  24.                               sym : Symbol;
  25.                               ind : CARDINAL;
  26.                             END;
  27.   K : CARDINAL;
  28.   buf : ARRAY [0..bufLen-1] OF CHAR;
  29.   
  30.  
  31. PROCEDURE Mark(n : CARDINAL);
  32. BEGIN
  33.   Invert(win,TRUE);
  34.   WriteCard(win,n,1);
  35.   Invert(win,FALSE);
  36. END Mark;
  37.  
  38.  
  39. PROCEDURE GetCh;
  40. BEGIN
  41.   ReadChar(source,ch);
  42.   Write(win,ch);
  43. END GetCh;
  44.  
  45.  
  46. PROCEDURE Diff(u,v : CARDINAL) : INTEGER;
  47. VAR
  48.   w : CARDINAL;
  49.   
  50. BEGIN
  51.   w := ORD(buf[u]);
  52.   LOOP
  53.     IF w=0 THEN 
  54.        RETURN 0;
  55.     ELSIF buf[u] # buf[v] THEN
  56.        RETURN INTEGER(buf[u]) - INTEGER(buf[v]);
  57.     ELSE
  58.        INC(u);
  59.        INC(v);
  60.        DEC(w);
  61.     END;
  62.   END;
  63. END Diff;
  64.  
  65.  
  66. PROCEDURE KeepId;
  67. BEGIN
  68.   id := id1;
  69. END KeepId;
  70.  
  71.  
  72. PROCEDURE Identifier;
  73. VAR
  74.   k,l,m : CARDINAL;
  75.   d : INTEGER;
  76.   
  77. BEGIN
  78.   id1 := id;
  79.   IF id1<bufLen THEN
  80.      INC(id1);
  81.   END;
  82.   REPEAT
  83.     IF id1<bufLen THEN
  84.        buf[id1] := ch;
  85.        INC(id1);
  86.     END;
  87.     GetCh;
  88.   UNTIL (ch<"0") OR ("9"<ch) AND 
  89.         (CAP(ch)<"A") OR ("Z"<CAP(ch));
  90.   buf[id] := CHR(id1-id);
  91.   k := 1;
  92.   l := K;
  93.   REPEAT 
  94.     m := (k+l) DIV 2;
  95.     d := Diff(id,keyTab[m].ind);
  96.     IF d<=0 THEN
  97.        l := m - 1;
  98.     END;
  99.     IF d>=0 THEN
  100.        k := m + 1;
  101.     END;
  102.   UNTIL k>l;
  103.   IF k>l+1 THEN
  104.      sym := keyTab[m].sym;
  105.   ELSE
  106.      sym := ident;
  107.   END;
  108. END Identifier;
  109.  
  110.  
  111. PROCEDURE Number;
  112. VAR
  113.   i,j,k,d : CARDINAL;
  114.   dig : ARRAY [0..31] OF CHAR;
  115.   
  116. BEGIN
  117.   sym := number;
  118.   i := 0;
  119.   REPEAT
  120.     dig[i] := ch;
  121.     INC(i);
  122.     GetCh;
  123.   UNTIL (ch<"0") OR ("9" < ch) AND (CAP(ch)<"A") OR ("Z"<CAP(ch));
  124.   j := 0;
  125.   k := 0;
  126.   REPEAT
  127.     d := CARDINAL(dig[j]) - 60B;
  128.     IF (d<10) AND ((maxCard-d) DIV 10 >=k) THEN 
  129.        k := 10*k + d;
  130.     ELSE
  131.        Mark(30);
  132.        k := 0;
  133.     END;
  134.     INC(j);
  135.   UNTIL j=i;
  136.   num := k;
  137. END Number;
  138.  
  139.  
  140. PROCEDURE GetSym;
  141. VAR
  142.   xch : CHAR;
  143.   
  144.  
  145.   PROCEDURE Comment;
  146.   BEGIN
  147.     GetCh;
  148.     REPEAT
  149.       WHILE ch # "*" DO
  150.         GetCh;
  151.       END;
  152.       GetCh;
  153.     UNTIL ch = ")";
  154.     GetCh;
  155.   END Comment;
  156.   
  157.  
  158. BEGIN
  159.   BusyRead(xch);
  160.   IF xch>0C THEN 
  161.      Read(xch);
  162.   END;
  163.   LOOP
  164.     IF ch<=" " THEN
  165.        IF ch=0C THEN
  166.           ch := " ";
  167.           EXIT;
  168.        END;
  169.        GetCh;
  170.     ELSIF ch>=177C THEN
  171.        GetCh;
  172.     ELSE
  173.        EXIT;
  174.     END;
  175.   END;
  176.   CASE ch OF
  177.     " " : sym := eof; ch := 0C;         |
  178.     "!" : sym := write; GetCh;          |
  179.     '"' : sym := null; GetCh;           |
  180.     "#" : sym := neq; GetCh;            |
  181.     "$" : sym := null; GetCh;           |
  182.     "%" : sym := null; GetCh;           |
  183.     "&" : sym := null; GetCh;           |
  184.     "'" : sym := null; GetCh;           |
  185.     "(" : GetCh;
  186.           IF ch="*" THEN
  187.              Comment;
  188.              GetSym;
  189.           ELSE
  190.              sym := lparen;
  191.           END; |
  192.     ")" : sym := rparen; GetCh;         |
  193.     "*" : sym := times; GetCh;          |
  194.     "+" : sym := plus; GetCh;           |
  195.     "-" : sym := minus; GetCh;          |
  196.     "." : sym := period; GetCh;         |
  197.     "/" : sym := div; GetCh;            |
  198.     "0".."9" : Number;                  |
  199.     ":" : GetCh;    
  200.           IF ch="=" THEN
  201.              GetCh;
  202.              sym := becomes;
  203.           ELSE
  204.              sym := null;
  205.           END; |
  206.     ";" : sym := semicolon; GetCh;      |
  207.     "<" : GetCh;
  208.           IF ch="=" THEN
  209.              GetCh;
  210.              sym := leq;
  211.           ELSE
  212.              sym := lss;
  213.           END; |
  214.     "=" : sym := eql; GetCh;            |
  215.     ">" : GetCh;
  216.           IF ch="=" THEN
  217.              GetCh;
  218.              sym := geq;
  219.           ELSE
  220.              sym := gtr;
  221.           END; |
  222.     "?" : sym := read; GetCh;           |
  223.     "@" : sym := null; GetCh;           |
  224.     "A".."Z" : Identifier;              |
  225.     "a".."z" : Identifier;              |
  226.     "{".."~" : sym := null; GetCh;      |
  227.   ELSE
  228.     sym := null;
  229.     GetCh;
  230.   END;   
  231. END GetSym;
  232.  
  233.  
  234. PROCEDURE InitScanner;
  235. BEGIN
  236.   ch := " ";
  237.   IF id0=0 THEN
  238.      id0 := id;
  239.   ELSE
  240.      id := id0;
  241.      Write(win,14C);
  242.   END;
  243. END InitScanner;
  244.  
  245.  
  246. PROCEDURE CloseScanner;
  247. BEGIN
  248.   CloseTextWindow(win);
  249. END CloseScanner;
  250.  
  251.  
  252. PROCEDURE EnterKW(sym : Symbol; name : ARRAY OF CHAR);
  253. VAR
  254.   l,L : CARDINAL;
  255.   
  256. BEGIN
  257.   INC(K);
  258.   keyTab[K].sym := sym;
  259.   keyTab[K].ind := id;
  260.   l := 0;
  261.   L := HIGH(name);
  262.   buf[id] := CHR(L+2);
  263.   INC(id);
  264.   WHILE l<=L DO
  265.     buf[id] := name[l];
  266.     INC(id);
  267.     INC(l);
  268.   END;
  269. END EnterKW;
  270.  
  271.  
  272. BEGIN
  273.   K := 0;
  274.   id := 0;
  275.   id0 := 0;
  276.   EnterKW(do,"DO");
  277.   EnterKW(if,"IF");
  278.   EnterKW(end,"END");
  279.   EnterKW(odd,"ODD");
  280.   EnterKW(var,"VAR"); 
  281.   EnterKW(call,"CALL");
  282.   EnterKW(then,"THEN");
  283.   EnterKW(begin,"BEGIN");
  284.   EnterKW(const,"CONST");
  285.   EnterKW(while,"WHILE");
  286.   EnterKW(procedure,"PROCEDURE");
  287.   OpenTextWindow(win,WindowElements{Title},0,20,640,140,"PROGRAM");
  288. END PL0Scanner.
  289.  
  290.  
  291.         
  292.